/*
* Copyright (C) 2020 ~ 2024 chaigec All Rights Reserved.
*
* Author:     chaigec <chaigec@163.com>
* Maintainer: chaigec <chaigec@163.com>

 * Use of this source code is governed by MIT license that can be found in the
 * LICENSE file in the root of the source tree. All contributing project authors
 * may be found in the AUTHORS file in the root of the source tree.
*/

#include "MkHttpMediaServer.h"
#include "MkHttpMediaSession.h"
#include "MkHttp/MkHttpSession.h"
#include "MkUtil/MkUtil.h"
#include "MkFlv/MkFlvMuxer.h"
#include "MkMedia/MkFileSource.h"
#include "MkUtil/MkLog.h"

CMkHttpMediaServer::CMkHttpMediaServer(CMkEventPool* pEventPool, CMkTimer* pTimer, const MkHttpJsonRequestCallback& HttpReqCb, const MkWsAccessedCallback& WsAccessedCb, const MkMediaCallbacks& MediaCallbacks)
    : CMkHttpApi(pEventPool, pTimer)
    , m_HttpRequestCallBack(HttpReqCb)
    , m_WsAccessedCb(WsAccessedCb)
    , m_MediaCbs(MediaCallbacks)
{

}

CMkTcpSession* CMkHttpMediaServer::CreateNewSession(CMkEvent *pEvent, CMkTimer* pTimer)
{
    return new CMkHttpMediaSession(pEvent, pTimer, this);
}

Uint32 CMkHttpMediaServer::OnSessionEventRemoved(CMkTcpSession* pSession)
{
    CMkHttpMediaSession* pFlvConsumer = dynamic_cast<CMkHttpMediaSession*>(pSession);
    if (m_MediaCbs.ConsumerClosedCb
        && pFlvConsumer
        && pFlvConsumer->IsWebSocket()) {
        m_MediaCbs.ConsumerClosedCb(pFlvConsumer->GetParentSessionId(), MkMediaConsumeWsFlv, pFlvConsumer->GetConsumerId());
    }
    return CMkHttpServer::OnSessionEventRemoved(pSession);
}

Uint32 CMkHttpMediaServer::OnRecvRequest(CMkHttpSession* pSession, const CMkHttpRequest& Request)
{
    CMkHttpMediaSession *pMediaSession = dynamic_cast<CMkHttpMediaSession*>(pSession);
    if (!m_MediaCbs.ConsumerAddCb
        || !m_MediaCbs.GetSourceParamCb
        || !pMediaSession) {
        pSession->SendReply(MkHttpStateNotFound);
        pSession->Close();
        return SocketClosed;
    }
    const MkString Path = Request.GetUri().GetUriPath();
    MkHttpMethod Method = Request.GetMethod();
    Uint32 ErrorCode = NoneError;
    //play ws-flv
    MkString EndFix = ".flv";
    if (MkHttpMethodGet == Method
        && CMkUtil::EndByString(Path, EndFix)) {
        MkString RealPath = Path.substr(0, Path.size() - EndFix.size());
        CMkVideoParam VideoParam;
        CMkAudioParam AudioParam;
        Uint32 Duration;
        Uint32 FileSize;
        MkString SourceSession;
        ErrorCode = m_MediaCbs.GetSourceParamCb(RealPath, VideoParam, AudioParam, Duration, FileSize, SourceSession);
        if (NoneError != ErrorCode) {
            pSession->SendReply(MkHttpStateNotFound);
            pSession->Close();
            return SocketClosed;
        }
        ErrorCode = pSession->SendWebsocketConnectResponse(Request);
        if (NoneError != ErrorCode) {
            MkErrorLog("send websocet response failed\n");
            pSession->SendReply(MkHttpStateBadRequest);
            pSession->Close();
            return ErrorCode;
        }
        ErrorCode = m_MediaCbs.ConsumerAddCb(SourceSession, new CMkWsFlvConsume, pMediaSession);
        return NoneError;
    }
    return CMkHttpApi::OnRecvRequest(pSession, Request);
}

Uint32 CMkHttpMediaServer::OnRequestJsonParse(const MkHttpMethod& Method, const MkString& Path, const MkMapString& MapQuery, const Json::Value& JsonReq, const MkHttpResponseJsonCb& cb)
{
    if (m_HttpRequestCallBack) {
        return m_HttpRequestCallBack(Method, Path, MapQuery, JsonReq, cb);
    }
    return SystemError;
}

Uint32 CMkHttpMediaServer::OnWebsocketRecved(CMkHttpSession* pSession, const MkString& Message)
{
    Uint32 ErrorCode = NoneError;
    Json::Value JsonRequest;
    try {
        Json::CharReaderBuilder b;
        Json::CharReader *reader(b.newCharReader());
        if (!reader) {
            ErrorCode = MallocFailed;
        } else {
            MkString errs;
            reader->parse(Message.c_str(), Message.c_str() + Message.size(), &JsonRequest, &errs);
            delete reader;
            MkString ControlType = JsonRequest["controlType"].asString();
            MkPlaybackControlType MkControlType = CMkMediaUtil::GetInstance().GetPlaybackControlType(ControlType);
            if (MkControlUnknown != MkControlType) {
                float fSpeed = JsonRequest["speed"].asFloat();
                Uint32 OffsetSec = JsonRequest["offsetSec"].asUInt();
                if (m_MediaCbs.ConsumerPlayCtrlCb) {
                    m_MediaCbs.ConsumerPlayCtrlCb(dynamic_cast<CMkHttpMediaSession*>(pSession), MkControlType, fSpeed, OffsetSec);
                }
            }
        }
    } catch (Json::Exception &e) {
        MkErrorLog("json parse error:%s\n", e.what());
    }
    return CMkHttpApi::OnWebsocketRecved(pSession, Message);
}

Uint32 CMkHttpMediaServer::OnWebSockekAccessed(CMkHttpSession* pSession)
{
    if (m_WsAccessedCb) {
        m_WsAccessedCb(pSession);
    }
    return NoneError;
}

CMkHttpMediaServer::~CMkHttpMediaServer()
{

}